/**
 * FileName: UserServiceImpl
 * Author: TangZaoBang
 * Date: 2023/04/29 22:45
 * Description:
 * <p>
 * History:
 * <author> TangZaoBang
 * <time> 2023/04/29 22:45
 * <version> 1.0.0
 * <desc> 版本描述
 */

package com.bosssoft.quickstart.demo.service.impl;

import com.bosssoft.quickstart.demo.constant.GlobalConstant;
import com.bosssoft.quickstart.demo.dao.entity.User;
import com.bosssoft.quickstart.demo.dao.mapper.UserMapper;
import com.bosssoft.quickstart.demo.exception.BizErrorCode;
import com.bosssoft.quickstart.demo.exception.BusinessException;
import com.bosssoft.quickstart.demo.pojo.dto.IdVersion;
import com.bosssoft.quickstart.demo.pojo.dto.UserDTO;
import com.bosssoft.quickstart.demo.pojo.query.UserQuery;
import com.bosssoft.quickstart.demo.pojo.vo.CommonPage;
import com.bosssoft.quickstart.demo.service.UserService;
import com.bosssoft.quickstart.demo.utils.IdGenerator;
import com.bosssoft.quickstart.demo.utils.MyBeanUtils;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import tk.mybatis.mapper.entity.Example;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.*;

/**
 * @Class UserServiceImpl
 * @Description UserService的实现类
 * @Author TangZaoBang
 * @Date 2023/04/29 22:45
 * @Version
 */
@Slf4j
@Validated
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IdGenerator idGenerator;

    /**
     * 先非空，同时要满足业务规则要求：身份证号不可重复
     * 满足后插入
     *
     * @param userDTO 接收到的User
     * @return java.lang.Boolean
     * @author TangZaoBang
     * @date 2023/04/29 23:07
     */
    @Override
    public Boolean add(@NotNull @Valid UserDTO userDTO) {
        //业务规则校验身份证号不可重复
        if (findUserByCitizenId(userDTO.getCitizenId(), null) != null) {
            throw new BusinessException(BizErrorCode.DATA_SEARCH_FOUND_MANNY, "身份证号已经存在");
        }
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        user.setId(idGenerator.snowflakeId());
        user.setCreatedTime(LocalDate.now());
        user.setCreatedBy(GlobalConstant.DEFAULT_CREATOR_ID);
        user.setUpdatedBy(GlobalConstant.DEFAULT_CREATOR_ID);
        user.setUpdatedTime(LocalDate.now());
        user.setVersion(idGenerator.snowflakeId());
        user.setStatus(GlobalConstant.ROW_DATA_STATUS_ACTIVE);
        return userMapper.insert(user) > 0;
    }
/**
 * removeUserById 删除User
 * @author TangZaoBang
 * @date 2023/04/30 00:28
 * @param id user的id
 * @return java.lang.Boolean
 */
    @Override
    public Boolean removeUserById(@NotNull Long id) {
        if (findUserById(id).getCitizenId()==null){
            throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND,"没有此用户");
        }
        return userMapper.deleteByPrimaryKey(id)>0;
    }
    /**
     * findUserById
     * @author TangZaoBang
     * @date 2023/04/30 11:30
     * @param id Id
     * @return java.lang.Boolean
     */

    @Override
    public UserDTO findUserById( @NotNull Long id) {
        User user = userMapper.selectByPrimaryKey(id);
        return user==null? new UserDTO(): MyBeanUtils.copyProperties(user,UserDTO::new);
    }

/**
 * 判断系统不存在相同身份证号的 不存在就更新
 * @author TangZaoBang
 * @date 2023/05/01 11:10
 * @param userDTO userDTO
 * @return java.lang.Boolean
 */
    @Override
    public Boolean updateUser(@NotNull @Valid  UserDTO userDTO) {
        Long id = userDTO.getId();
        if(null==id){
            throw new BusinessException(BizErrorCode.PARAM_VALID_FIELD_REQUIRE,"id为主键列不可为空");
        }
        if (findUserById(id)==null){
            throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND,"未找到该用户，请先增加用户");
        }
        // 判断系统不存在相同身份证号的
        if (findUserByCitizenId(userDTO.getCitizenId(), id)!=null){
            throw new BusinessException(BizErrorCode.DATA_SEARCH_FOUND_MANNY,
                    "身份证号系统已经使用，请换一个");
        }
        User user=new User();
        BeanUtils.copyProperties(userDTO,user);
        user.setUpdatedTime(LocalDate.now());
        user.setUpdatedBy(GlobalConstant.DEFAULT_MODIFIER_ID);
        // 更新版本id
        user.setVersion(idGenerator.snowflakeId());
        Example example=new Example(User.class);
        example.createCriteria()
                .andEqualTo(GlobalConstant.COLUMN_ID, id).andEqualTo(GlobalConstant.COLUMN_VERSION,userDTO.getVersion());
        return userMapper.updateByExampleSelective(user,example)>0;
    }

    /**
     * 通过 id 和 version 删除User 要求id和version 都要一致
     * @author TangZaoBang
     * @date 2023/05/01 10:25
     * @param id id
     * @param version  version
     * @return java.lang.Boolean
     */
    @Override
    public Boolean removeUserByIdAndVersion(@NotNull  Long id, @NotNull  Long version) {
        if (findUserById(id).getCitizenId()==null){
            throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND,"没有此用户");
        }
        Example example=new Example(User.class);
        example.createCriteria()
                .andEqualTo(GlobalConstant.COLUMN_ID,id).andEqualTo(GlobalConstant.COLUMN_VERSION,version);
        return userMapper.deleteByExample(example)>0;
    }

    /**
     *  在事务中启用批量删除
     * @author TangZaoBang
     * @date 2023/05/01 17:31
     * @param idVersions 传入的id version的集合
     * @return java.lang.Boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeUsers(@NotEmpty IdVersion[] idVersions) {
        // 将 IdVersion 数组转换为 id 数组和 version 数组
        Long[] ids = Arrays.stream(idVersions).map(IdVersion::getId).toArray(Long[]::new);
        Long[] versions = Arrays.stream(idVersions).map(IdVersion::getVersion).toArray(Long[]::new);
        // 构建条件
        Example example = new Example(User.class);
        example.createCriteria().andIn(GlobalConstant.COLUMN_ID, Arrays.asList(ids)).andIn(GlobalConstant.COLUMN_VERSION, Arrays.asList(versions));
        // 执行删除
        List<User> users = userMapper.selectByExample(example);
        int count = userMapper.deleteByExample(example);
        // 检查删除记录数量是否符合预期
        if (count != ids.length) {
            // 记录删除失败的数据
            Set<Long> failedIds = new HashSet<>(Arrays.asList(ids));
            for (User user : users) {
                failedIds.remove(user.getId());
            }
            throw new BusinessException(BizErrorCode.DATA_DELETE_NOT_FOUND, "删除失败的数据id：" + failedIds);
        }
        return true;
    }
/**
 * 根据用户查询条件分页查询用户信息
 * @author TangZaoBang
 * @date 2023/05/01 18:36
 * @param userQuery 查询的条件
 * @return com.bosssoft.quickstart.demo.pojo.vo.CommonPage<com.bosssoft.quickstart.demo.pojo.dto.UserDTO>
 */
    @Override
    public CommonPage<UserDTO> search(@NotNull @Valid UserQuery userQuery) {
        //  创建用户查询条件示例
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        // 如果查询条件中包含姓名，则将姓名作为查询条件之一
        if (!StringUtils.isEmpty(userQuery.getName())) {
            criteria.andLike(GlobalConstant.COLUMN_NAME, "%" + userQuery.getName().trim() + "%");
        }
        // 如果查询条件中包含身份证号，则将身份证号作为查询条件之一
        if (!StringUtils.isEmpty(userQuery.getCitizenId())) {
            criteria.andLike(GlobalConstant.COLUMN_CITIZEN_ID, "%" + userQuery.getCitizenId().trim() + "%");
        }
        //按更新时间倒序排列
        example.setOrderByClause("updated_time DESC");

        // 构建包含分页信息的列表

        PageMethod.startPage(userQuery.getPageIndex(), userQuery.getPageSize());
        List<User> userList = userMapper.selectByExample(example);
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        //  将分页结果转换为DTO列表
        List<UserDTO> userDTOList = MyBeanUtils.copyList(userList, UserDTO::new,null);
        // 将分页结果封装成 CommonPage 对象返回
        return new CommonPage<>(pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getPages(), userDTOList);
    }


    /**
     * 通过身份证号找user
     * @author TangZaoBang
     * @date 2023/04/30 00:19
     * @param citizenId 身份证号
     * @param exclusiveId  要排除的id
     * @return com.bosssoft.quickstart.demo.dao.entity.User 不存在就是null
     */
    private User findUserByCitizenId(String citizenId, Long exclusiveId) {
        Example example = new Example(User.class);
        if (exclusiveId == null) {
            example.createCriteria().andEqualTo(GlobalConstant.COLUMN_CITIZEN_ID, citizenId);
        } else {
            // 排除当前记录
            example.createCriteria().andEqualTo(GlobalConstant.COLUMN_CITIZEN_ID, citizenId).
                    andNotEqualTo(GlobalConstant.COLUMN_ID, exclusiveId);
        }
        return userMapper.selectOneByExample(example);
    }
}
